﻿using System.ComponentModel;
using System.Threading.Tasks;

namespace Red.Launcher.Utilities
{
    public interface IEnvironmentalVariableSource
    {
        #region Properties

        bool HasConfig { get; }
        bool HasValues { get; }

        #endregion Properties

        #region Methods

        void SetEnvironmentVariables();
        void ClearEnvironmentVariables();

        #endregion Methods
    }

    public class EnvironmentalVariableHelper
    {
        #region Private Data

        private bool _refreshingEnvironmentalVariables;
        private bool _queueEnvironmentalVariablesRefresh;

        #endregion Private Data

        #region Public Properties

        public IEnvironmentalVariableSource Source { get; set; }

        #endregion Public Properties

        #region C-Tor

        public EnvironmentalVariableHelper()
        {
            Settings.StaticPropertyChanged += Settings_StaticPropertyChanged;
        }

        #endregion C-Tor

        #region Public Methods

        public void Shutdown()
        {
            if ( !Settings.PersistEnvironmentalVariablesAfterShutdown )
            {
                Source.ClearEnvironmentVariables();
            }
        }

        public async Task Refresh()
        {
            if ( Source == null )
                return;

            if ( !Source.HasConfig )
                return;

            if ( _refreshingEnvironmentalVariables )
            {
                _queueEnvironmentalVariablesRefresh = true;
                return;
            }

            _refreshingEnvironmentalVariables = true;
            bool setVars = Settings.AddRuntimeToEnvironmentalVariables;

            await Task.Run( () => { Refresh( setVars ); } );

            _refreshingEnvironmentalVariables = false;

            if ( _queueEnvironmentalVariablesRefresh )
            {
                _queueEnvironmentalVariablesRefresh = false;
                await Refresh();
            }
        }

        #endregion Public Methods

        #region Private Methods

        private void Refresh( bool setVars )
        {
            if ( setVars && Source.HasValues )
            {
                Source.SetEnvironmentVariables();
            }
            else
            {
                Source.ClearEnvironmentVariables();
            }
        }

        #endregion Private Methods

        #region Event Handlers

        private async void Settings_StaticPropertyChanged( object sender, PropertyChangedEventArgs e )
        {
            switch ( e.PropertyName )
            {
                case "AddRuntimeToEnvironmentalVariables":
                    await Refresh();
                    break;
            }
        }

        #endregion Event Handlers
    }
}
